package nl.haemers.data.reflection 
{
	import flash.utils.getDefinitionByName;
	
	import nl.haemers.data.utils.ObjectUtils;
	import nl.haemers.data.serializers.ObjectSerializer;
	import nl.haemers.data.constants.ReflectionConstants;
	
	/**
	 * ...
	 * @author Jonathan Haemers
	 */
	public class Accessor implements IAccessor 
	{
		private var _name				:String;
		private var _access				:String;
		private var _type				:String;
		private var _declaredBy			:String;
		
		private var _dataType			:String;
		
		private var _level				:int;
		private var _metadatas			:IMetadatas;
		
		private var _serializeName		:String;
		private var _hasSerialize		:Boolean;
		private var _objType			:Type;
		
		public function Accessor() 
		{			
		}
		
		/** Public methods **/
		public function hasSerialize():Boolean 
		{
			return _hasSerialize;
		}
		
		public function hasChild() : Boolean
		{
			return _objType != null;
		}
		
		public function hasParent():Boolean 
		{
			return false;
		}
		
		public function toString() : String
		{
			return _serializeName;
		}
		
		/** Getters & Setters **/
		
		public function get name():String 
		{
			return _name;
		}
		
		public function get serializeName() : String
		{ 
			return _serializeName; 
		}
		
		public function get acces():String 
		{
			return _access;
		}
		
		public function get type():String 
		{
			return _type;
		}
		
		public function get declaredBy():String 
		{
			return _declaredBy;
		}
		
		public function get level():int 
		{
			return -1;
		}
		
		public function get metadatas() : IMetadatas
		{
			return _metadatas;
		}
		
		public function get objectType() : Type
		{
			return _objType;
		}
		
		public function get dataType() : String
		{ 
			return _dataType;
		}
		
		/** Protected methods **/
		
		/** Private methods **/
		
		/** Static methods **/
		internal static function init(xml:XML) : IAccessor
		{
			var accessor:Accessor = new Accessor();
			accessor._name = xml.@name;
			
			accessor._metadatas = Metadatas.init(xml);
			var serialize:IMetadata = accessor._metadatas.getMetadata(ReflectionConstants.OBJECT_ATTRIBUTE);
			accessor._hasSerialize = serialize != null;
			accessor._serializeName = accessor._hasSerialize ? serialize.args.getArg(ReflectionConstants.ATTRIBUTE_NAME).value : accessor._name;
			
			accessor._access = xml.@access;
			accessor._type = xml.@type;
			accessor._declaredBy = xml.@declaredBy;
			accessor._dataType = ObjectUtils.getDataType(xml.@type);
			
			if(!ObjectUtils.isDataType(accessor.type))
			{
				accessor._objType = createType(accessor);
			}
			
			return accessor;
		}
		
		private static function createType(accessor:IAccessor) : Type
		{
			var classRef:Class = getDefinitionByName(accessor.type) as Class;
			return ObjectSerializer.getType(classRef);
		}
		
		private static function checkType(accessor:IAccessor) : void
		{
			var type:String = accessor.type;
			
			//check type
				//if type is datatype do nothing
				//if type is collection what to do?
					/* I guess we need to make an new type Type 
					 * The accessor becomes a Type object... hmm not possible with the interfaces...
					 **/
		}
		/*
			<accessor name="url" access="readwrite" type="String" declaredBy="nl.haemers.test.data.vo::PageVO">
			  <metadata name="Serialize">
				<arg key="name" value="page"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="546"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="611"/>
			  </metadata>
			</accessor>
		*/
	}

}